package utils

import (
	"archive/zip"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func DirIsExist(dir string) {
	//exeCurDir, _ := filepath.Abs(filepath.Dir(os.Args[0]))

	_, err := os.Stat(dir)
	//文件夹或者文件不存在
	if err != nil {
		err := os.MkdirAll(dir, 0777)
		if err != nil {
			log.Printf("创建%s文件夹失败 %v\n", dir, err)
		}
		_ = os.Chmod(dir, 0777)
	}
}

func FileIsExist(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}

func FileCreate(name string) error {
	fp, err := os.Create(name)
	if err != nil {
		return err
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(fp)

	_ = fp.Sync()
	return nil
}

func FileWrite(dir string, data []byte) error {
	fp, err := os.OpenFile(dir, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		return err
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(fp)

	_, err = fp.Write(data)
	if err != nil {
		return err
	}
	_ = fp.Sync()
	return nil
}

func FileRead(dir string) ([]byte, error) {
	data, err := ioutil.ReadFile(dir)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func FileRemove(dir string) error {
	exeCurDir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
	err := os.Remove(exeCurDir + dir)
	if err != nil {
		return err
	}
	return nil
}

func FileCopy(src, dst string) error {
	if _, err := os.Stat(dst); os.IsNotExist(err) {
		in, err := os.Open(src)
		if err != nil {
			return err
		}
		defer in.Close()

		out, err := os.Create(dst)
		if err != nil {
			return err
		}
		defer out.Close()

		_, err = io.Copy(out, in)
		if err != nil {
			return err
		}
	}
	return nil
}

//压缩多个路径到一个zip文件里面
//Param 1: 需要添加到zip文件里面的路径
//Param 2: 打包后zip文件名称
func CompressDirsToZip(srcDirMap []string, fileName string) error {

	//创建zip文件
	newZipFile, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer func(newZipFile *os.File) {
		err = newZipFile.Close()
		if err != nil {

		}
	}(newZipFile)

	//打开zip文件
	zipWriter := zip.NewWriter(newZipFile)
	defer func(zipWriter *zip.Writer) {
		err = zipWriter.Close()
		if err != nil {

		}
	}(zipWriter)

	for _, v := range srcDirMap {
		//遍历文件夹
		err = filepath.Walk(v, func(path string, info os.FileInfo, _ error) error {

			//如果是源路径，提前进行下一个遍历(没明白这个判断)
			//if path == v {
			//	return nil
			//}

			// 获取文件头信息
			header, _ := zip.FileInfoHeader(info)
			header.Name = strings.TrimPrefix(path, v+`/`)

			// 判断文件是不是文件夹
			if info.IsDir() {
				header.Name += `/`
			} else {
				// 设置：zip的文件压缩算法
				header.Method = zip.Deflate
			}

			// 创建压缩包头部信息
			writer, _ := zipWriter.CreateHeader(header)
			if !info.IsDir() {
				file, _ := os.Open(path)
				defer func(file *os.File) {
					err = file.Close()
					if err != nil {
					}
				}(file)
				_, err = io.Copy(writer, file)
				if err != nil {
					return err
				}
			}
			return nil
		})
	}

	return err
}

//压缩单个路径到一个zip文件里面
//Param 1: 需要添加到zip文件里面的路径
//Param 2: 打包后zip文件名称
func CompressDirToZip(srcDirMap string, fileName string) error {

	//创建zip文件
	newZipFile, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer func(newZipFile *os.File) {
		err = newZipFile.Close()
		if err != nil {

		}
	}(newZipFile)

	//打开zip文件
	zipWriter := zip.NewWriter(newZipFile)
	defer func(zipWriter *zip.Writer) {
		err = zipWriter.Close()
		if err != nil {

		}
	}(zipWriter)

	//遍历文件夹
	err = filepath.Walk(srcDirMap, func(path string, info os.FileInfo, _ error) error {
		//如果是源路径，提前进行下一个遍历(没明白这个判断)
		//if path == v {
		//	return nil
		//}

		// 获取文件头信息
		header, _ := zip.FileInfoHeader(info)
		header.Name = strings.TrimPrefix(path, srcDirMap+`\`)

		// 判断文件是不是文件夹
		if info.IsDir() {
			header.Name += `/`
		} else {
			// 设置：zip的文件压缩算法
			header.Method = zip.Deflate
		}

		// 创建压缩包头部信息
		writer, _ := zipWriter.CreateHeader(header)
		if !info.IsDir() {
			file, _ := os.Open(path)
			defer func(file *os.File) {
				err = file.Close()
				if err != nil {
				}
			}(file)
			_, err = io.Copy(writer, file)
			if err != nil {
				return err
			}
		}
		return nil
	})

	return err
}

//压缩单个路径到一个zip文件里面
//Param 1: 需要添加到zip文件里面的路径
//Param 2: 打包后zip文件名称
func CompressFilesToZip(srcFiles []string, dstFileName string) error {
	//创建zip文件
	newZipFile, err := os.Create(dstFileName)
	if err != nil {
		return err
	}
	defer func(newZipFile *os.File) {
		err = newZipFile.Close()
		if err != nil {

		}
	}(newZipFile)

	//打开zip文件
	zipWriter := zip.NewWriter(newZipFile)
	defer func(zipWriter *zip.Writer) {
		err = zipWriter.Close()
		if err != nil {

		}
	}(zipWriter)

	for _, file := range srcFiles {
		fileToZip, err := os.Open(file)
		if err != nil {
			return err
		}
		defer fileToZip.Close()

		// Get the file information
		info, err := fileToZip.Stat()
		if err != nil {
			return err
		}

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		// Using FileInfoHeader() above only uses the basename of the file. If we want
		// to preserve the folder structure we can overwrite this with the full path.
		header.Name = filepath.Base(file)

		// Change to deflate to gain better compression
		// see http://golang.org/pkg/archive/zip/#pkg-constants
		header.Method = zip.Deflate

		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}
		_, err = io.Copy(writer, fileToZip)

	}

	return err
}

func CopyFile(srcPath, dstPath string) error {
	src, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return err
	}
	defer dst.Close()

	_, err = io.Copy(dst, src)
	return err
}

func CopyDir(srcDir, dstDir string) error {
	files, err := ioutil.ReadDir(srcDir)
	if err != nil {
		return err
	}

	for _, file := range files {
		srcPath := filepath.Join(srcDir, file.Name())
		dstPath := filepath.Join(dstDir, file.Name())

		if file.IsDir() {
			if err := os.MkdirAll(dstPath, file.Mode()); err != nil {
				return err
			}
			if err := CopyDir(srcPath, dstPath); err != nil {
				return err
			}
		} else {
			if err := CopyFile(srcPath, dstPath); err != nil {
				return err
			}
		}
	}

	return nil
}
